package gold;

import org.jbox2d.dynamics.Body;
import org.newdawn.slick.Animation;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.geom.Circle;
import org.newdawn.slick.geom.Polygon;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.state.StateBasedGame;

/**
 * A Sprite represents an element from the scene. 
 * It holds basic properties like the Image, the rectangle, the shape and flags.
 * Classes which inherits from Sprite can be the Characters, interactive elements, decor elements, etc.
 */
public class Sprite {
	protected int x; /* x, top left point of the bounding box of this element */
	protected int y; /* y, top left point of the bounding box of this element */
	protected int w; /* width of the bounding box of this element */
	protected int h; /* heigh of the bounding box of this element */
	protected Image image = null; /* image to load on the element */
	protected Animation animation = null; /* animation to load on the element */
	protected Shape shape = null; /* shape of the element (if not rectangular) */
	protected boolean shouldBeDestroy=false; /* whether the element should be destroyed */
	protected boolean shouldChangeSize=false; /* whether the element should be resized */
	protected boolean shouldRebond=false; /* whether the element should rebond */
	protected Color colorFilter = Color.white; /* Filter to apply on the object */
	protected boolean isHidden=false; /* whether the element should be hidden on the scene */
	protected boolean lightInDarkness=false; /* whether the element shines in the darkness */
	protected int lightSize=50; /* size of the light generated by the element in the darkness */
	protected Image lightImage=Global.setImage(Global.DEFAULT_LIGHT_IMAGE); /* image to use as a filter for light */
	protected Level level; /* level in which the sprite is encapsulated */
	protected InGameIndication indication= null; /* the indication to display when passing over the sprite */

	
	// Constructors
	public Sprite(){
		this.x=0;
		this.y=0;
		this.w=40;
		this.h=40;
	}	
	public Sprite(int _x, int _y){
		this.x = _x;
		this.y = _y;
	}
	public Sprite(int _x, int _y, int _w, int _h){
		this.x = _x;
		this.y = _y;
		this.w = _w;
		this.h = _h;
	}

	
	// Setters
	public void setLevelContainer(Level lvl){
		this.level = lvl;
	}
	public void setCoordinatesFromBody(Body b){
		this.x = (int)b.getPosition().x-this.w/2;
		this.y = Global.GAMEPLAYHEIGHT-(int)b.getPosition().y-this.h/2;
	}
	protected void setImage(String filename){
		try {
			if (filename==null) 
				this.image=null;
			else 
				this.image = new Image(Global.PATH_IMAGES_RESSOURCES+filename);
		} catch (SlickException e) {
			e.printStackTrace();
		}
	}
	protected void setAnimation(String filename, int tw, int th){
		try {
			SpriteSheet ss = new SpriteSheet(Global.PATH_SPRITES_RESSOURCES+filename,tw,th);
			this.animation = new Animation(ss,100);
		} catch (SlickException e) {
			e.printStackTrace();
		}
	}
	public void setTexture(String filename){
		// TODO: 
		//this.image.setTexture(new Texture());
	}
	protected void setFilter(Color _colorFilter){
		this.colorFilter = _colorFilter;
	}
	public void addPointToShape(int x, int y){
		if(shape==null){
			shape = new Polygon();
		}
		if(shape instanceof Polygon){
			((Polygon)shape).addPoint(x, y);			
		}
	}
	public void setCircleShapeO(float radius){
		shape = new Circle(x+w/2,y+h/2,radius);
	}
	public void setShouldBeDestroy(){
		shouldBeDestroy=true;
	}
	public void setIndication(int w, int h, String msg){
		indication = new InGameIndication(w,h,msg);
		if(this.level != null){
			this.level.addIndication(indication);
		}
	}
	public void setIndication(InGameIndication indic){
		indication=indic;
	}
	public void setHidden(boolean hideOrNot){
		isHidden=hideOrNot;
	}
	public void setLightSize(int _lightSize){
		this.lightInDarkness = true;
		this.lightSize = _lightSize;
		this.lightImage = Global.setImage(Global.DEFAULT_LIGHT_IMAGE).getScaledCopy(lightSize, lightSize);
	}
	
	
	// Getters
	public InGameIndication getIndication(){
		return indication;
	}
	public boolean getShouldBeDestroy(){
		return shouldBeDestroy;
	}
	public boolean isHidden(){
		return isHidden;
	}
	public int X(){
		return x;
	}	
	public int Y(){
		return y;
	}	
	public int W(){
		return w;
	}	
	public int H(){
		return h;
	}

	
	// Interaction methods 
	/** 
	 *	Check for a collision between two Sprite
	 *  @return whether the two Sprite are colliding
	*/
	public boolean rectCollideWithOther(Sprite other){
		if((((this.x >= other.x) && (this.x <= (other.x+other.w))) 
				|| (((this.x + this.w) >= other.x) && ((this.x + this.w) <= (other.x+other.w))))
				&& (((this.y >= other.y) && (this.y <= (other.y+other.h))) 
						|| (((this.y + this.h) >= other.y) && ((this.y + this.h) <= (other.y+other.h))))){
			return true;
		}
		else{
			return false;
		}
	}
	/** Activate the indication, which will be displayed at the bottom of the screen*/
	public void activateIndication(){
		if(indication!=null){
			indication.activate();
		}
	}


	// Draw
	public void draw(GameContainer container, StateBasedGame game, Graphics g){
		if(animation!=null){
			animation.draw(x, y, w, h, colorFilter);
		}
		else if(shape!=null){
			g.texture(shape, image, true);
		}
		else if(image!=null){
			image.draw(x, y, w, h);
		}
	}
	/** Method called when we are in alpha mode */
	public void drawLight(Graphics g, boolean alphaMode){
		lightImage.draw(x+w/2-lightSize/2, y+w/2-lightSize/2, new Color(0.0f,0.0f,0.0f,0.5f));
	}

}
